from abc import ABC, abstractmethod, abstractproperty
from typing import Generic, NoReturn, Optional, Self, TypeVar, Union


T = TypeVar("T", bound=Union[str, float])

# V = TypeVar("V", bound="Graph.Vertex")


class Collection(ABC):
    """
    集合
    """

    @abstractproperty
    def size(self) -> int:
        """集合元素个数

        Returns:
            _type_: 元素个数
        """
        raise NotImplementedError

    def __len__(self):
        """
        docstring
        """
        return self.size


class Vertex(ABC):
    """
    顶点
    """

    __slots__ = "__element"

    def __init__(self, element: T) -> None:
        """
        初始化
        """
        self.__element: T = element

    @property
    def element(self):
        """
        元素
        """
        return self.__element


class Edge(ABC):
    """
    边的抽象类
    """

    __slots__ = ("__origin", "__destination", "__weight")

    def __init__(
        self, origin: Vertex, destination: Vertex, weight: Optional[float] = None
    ):
        """初始化边。

        Args:
            origin (Vertex): 起始顶点
            destination (Vertex): 结束顶点
            weight (float, optional): 权重
        """
        self.__origin = origin
        self.__destination = destination
        if weight <= 0:
            raise ValueError
        self.__weight: float | None = weight

    @abstractproperty
    def outdegree(self) -> int:
        """
        出度
        """
        raise NotImplementedError

    @abstractproperty
    def indegree(self) -> int:
        """
        入度
        """
        raise NotImplementedError

    @property
    def weight(self) -> float | None:
        """
        权重
        """
        return self.__weight

    @weight.setter
    def weight(self, weight) -> NoReturn:
        """
        权重
        """
        self.__weight = weight

    @property
    def origin(self) -> Vertex:
        """
        起始端点
        """
        return self.__origin

    @origin.setter
    def origin(self, origin: Vertex):
        """
        起始端点
        """
        self.__origin: Vertex = origin

    def add_neighbor(self, vertex: Vertex):
        """
        docstring
        """
        raise NotImplementedError


class Graph(Collection, Generic[T]):
    """
    图
    """

    def __init__(self, directed: bool = False):
        """初始化

        Args:
            directed (bool, optional): 是否有向图. Defaults to False.
        """
        self.__directed: bool = directed

    @property
    def size(self) -> int:
        return len(list)

    @abstractmethod
    def add_edge(self, edge: Edge) -> None:
        """
        增加边
        """
        raise NotImplementedError

    @abstractmethod
    def add_vertex(self, vertex: Vertex) -> None:
        """
        增加顶点
        """
        raise NotImplementedError

    @abstractmethod
    def remove_edge(self, edge: Edge) -> None:
        """
        移除边
        """
        raise NotImplementedError

    @abstractmethod
    def remove_vertex(self, v: Edge) -> None:
        """
        移除顶点
        """
        raise NotImplementedError

    # @abstractproperty
    # def n(self) -> int:
    #     """
    #     顶点数量
    #     """
    #     raise NotImplementedError

    # @abstractproperty
    # def e(self) -> int:
    #     """
    #     边的数量
    #     """
    #     raise NotImplementedError


class AdjacencyMatrixGraph(Graph):
    """
    邻接矩阵图
    """

    __slots__ = ("__directed", "__incoming")

    def __init__(self, directed: bool = False) -> None:
        """初始化

        Args:
            directed (bool, optional): 是否有向图. Defaults to False.
        """
        self.__directed: bool = directed
        self.__incoming: list[list[int]] = []

    @abstractmethod
    def degree(self, vertex: Vertex) -> int:
        """
        docstring
        """
        raise NotImplementedError

    def add_edge(self, edge: Edge) -> None:
        """
        增加边
        """

    def add_vertex(self, vertex: Vertex) -> None:
        """
        增加顶点
        """
        raise NotImplementedError

    def remove_edge(self, edge: Edge) -> None:
        """
        移除边
        """
        raise NotImplementedError

    def size(self) -> int:
        return


def main():
    # c = Collection()
    g = Graph()
    print(g.size)

    # print(len(g))


if __name__ == "__main__":
    main()
